﻿/*
Copyright (c) 2010, hiSoft
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the hiSoft nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE HISOFT AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL HISOFT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

using System;
using System.IO;
using RecordPlaybackFramework;

namespace Orchard.Test.Library
{
    public class PackagingHelper:UIHelperBase
    {
        public MessagesHelper MessagesHelper;
        public LiveWriterHelper LiveWriterHelper;
        public PackagingHelper(TestLibrary settings) : base(settings)
        {
            MessagesHelper = new MessagesHelper(settings);
            LiveWriterHelper = new LiveWriterHelper(settings);
        }

        private int GetFeedIndexOnGalleryFeedsPage(Feed feed)
        {
            var count = (int)selenium.GetXpathCount(GalleryFeedsLocator);
            var index = 1;
            for (; index <= count; ++index)
            {
                string path = String.Format("{0}[{1}]/td[2]/a", GalleryFeedsLocator, index);
                var text = selenium.GetText(path);
                if (String.CompareOrdinal(feed.Url, text) == 0)
                    break;
            }

            if (index > count)
                throw new CaseFailureException(String.Format("Can't find feed {0} in Gallery Feeds page!", feed.Url));

            return index;
        }

        public void NavigateToInstalledModules()
        {
            selenium.Open("/Admin/Modules");
        }      

        public int GetModuleCount(string modulesLocator)
        {
            NavigateToInstalledModules();
            return (int)selenium.GetXpathCount(modulesLocator);
        }

        public void InstallModule(string modulePackage)
        {
            selenium.Open("/Packaging/PackagingServices/AddModule?returnUrl=%2FAdmin%2FModules");
            selenium.Type("ModulePackage", modulePackage);
            Submit();
        }

        public void ManageModulesUpdates()
        {
            if (!selenium.GetLocation().EndsWith("/Packaging/GalleryUpdates/ModulesUpdates"))
            {
                selenium.Open("/Packaging/GalleryUpdates/ModulesUpdates");
            }
        }

        public void UpdateModule(string moduleID)
        {
            ManageModulesUpdates();
            string locator = string.Format("//a[contains(@href, '/Packaging/PackagingServices/InstallGallery?packageId={0}')]", moduleID);
            ClickAndWait(locator);
            //Submit();
            
        }

        public string UpdateModuleOfDefaultFirst()  //return "moduleID-moduleName-moduleVersion"
        {
            ManageModulesUpdates();
            if (selenium.GetXpathCount("//div[@id='content']/div/ul/li") < 1)
                return "false";
            string moduleID = "";
            string locatorModuleLinkUrl = "//div[@id='content']/div/ul/li[1]/div/div[1]/div[1]/a@href";
            string locatorModuleNameAndVersion = "//div[@id='content']/div/ul/li[1]/div/div[1]/div[1]";
            string moduleNameAndVersion = selenium.GetText(locatorModuleNameAndVersion);
            string[] array = selenium.GetAttribute(locatorModuleLinkUrl).Split('/');
            foreach (string name in array)
            {
                if (name.Contains("Orchard.Module."))
                {
                    moduleID = name;
                    break;
                }
            }
            UpdateModule(moduleID);
            return moduleID.Replace("Orchard.Module.", "") + "-" + moduleNameAndVersion;
        }

        public bool IsOK_ValidateUpdateModuleByMessage(string moduleID)
        {            
            string thisBackUpModulePath = TestLibrary.Consts.OrchardBackUpModulesPath + "\\" + moduleID;
            if (!selenium.IsTextPresent("Successfully backed up local package to local folder "))
                return false;
            else if (!selenium.IsTextPresent("The module has been successfully installed"))
                return false;
            else if (!selenium.IsTextPresent("Successfully added 'Orchard.Module." + moduleID))
                return false;
            else if (!Directory.Exists(thisBackUpModulePath))
                return false;
            else return true;
        }

        public bool IsOK_EnableFeaturesOfPackageAndValidateStatusByMessage(string moduleId)
        {   
            bool result=true;
            string locatorFeaturesOfPackage = string.Format("//form[contains(@action,'/InstallPackageDetails?packageId=Orchard.Module.{0}')]/fieldset/div", moduleId);
            int featuresItemCountOfPackage =(int) selenium.GetXpathCount(locatorFeaturesOfPackage);
            for (int i = 0; i < featuresItemCountOfPackage; i++)
            {
                if (!selenium.IsChecked(string.Format("Features_{0}__Enable",i)))
                    selenium.Check(string.Format("Features_{0}__Enable", i));
            }
            string FeaturesNameOfPackage = "";
            string[] arrFeatures = new string[featuresItemCountOfPackage];
            for (int j = 0; j < featuresItemCountOfPackage; j++)
            {
                FeaturesNameOfPackage = selenium.GetAttribute(locatorFeaturesOfPackage + string.Format("/input[@id='Features_{0}__FeatureDescriptor_Name']@value",j));
                arrFeatures[j] = FeaturesNameOfPackage;
            }
            ClickAndWait("//button[@type='submit']");
            string message = "";
            for (int k = 0; k < featuresItemCountOfPackage; k++)
            {
                message = arrFeatures[k] + " was enabled";
                if (!MessagesHelper.GetMessagesOfCurrent().Contains(message))
                { result = false; break; }
            }
            return result;
        }

        public bool IsOK_DonotEnableFeaturesOfPackageAndValidateStatusByMessage(string moduleId)
        {           
            string locatorFeaturesOfPackage = string.Format("//form[contains(@action,'/InstallPackageDetails?packageId=Orchard.Module.{0}')]/fieldset/div", moduleId);
            int featuresItemCountOfPackage = (int)selenium.GetXpathCount(locatorFeaturesOfPackage);
            for (int i = 0; i < featuresItemCountOfPackage; i++)
            {
                if (selenium.IsChecked(string.Format("Features_{0}__Enable", i)))
                    selenium.Uncheck(string.Format("Features_{0}__Enable", i));
            }           
            ClickAndWait("//button[@type='submit']");
            string currentLocation = selenium.GetLocation();
            return currentLocation.Contains("/GalleryUpdates/ModulesUpdates");
        }

        public void InstallTheme(string themePackagePath)
        {
            selenium.Open("/Packaging/PackagingServices/AddTheme?returnUrl=%2FAdmin%2FThemes");
            selenium.Type("ThemePackage", themePackagePath);
            Submit();
        }      

        public void ManageGalaleryFeeds()
        {
            selenium.Open("/Packaging/Gallery/Sources");
        }

        public void BrowseGalleryModules()
        {
            selenium.Open("/Packaging/Gallery/Modules");
        }

        public Feed AddFeed(string url)
        {
            selenium.Open("/Packaging/Gallery/AddSource");   
            selenium.Type("Url", url);
            Submit();
            return new Feed(null,url);
        }

        public void RemoveFeed(Feed feed)
        {
            ManageGalaleryFeeds();
            int index = GetFeedIndexOnGalleryFeedsPage(feed);
            ClickAndWait(String.Format("{0}[{1}]/td[3]/a", GalleryFeedsLocator, index));            
        }

        public string GetTitleOfFeed(Feed feed)
        {
            ManageGalaleryFeeds();
            int index = GetFeedIndexOnGalleryFeedsPage(feed);
            return selenium.GetText(String.Format("{0}[{1}]/td[1]", GalleryFeedsLocator, index));
        }       

        public int GetFeedCount()
        {
            ManageGalaleryFeeds();
            return (int)selenium.GetXpathCount(GalleryFeedsLocator);
        }

        public void ApplyPageSize(string pageSize)
        {
            selenium.Select("pageSize", String.Format("label={0}", pageSize));          
        }

        public void ApplySortCondition(string sortCondition)
        {
            selenium.Select("filterResults", String.Format("label={0}", sortCondition));
            selenium.Click("//button[@type='submit']");
            selenium.WaitForPageToLoad("60000");
        }

        public void SortByCondition(string sortCondition)
        {
            
            selenium.Click("apply-bulk-actions");
            selenium.Select("filterResults", String.Format("label={0}", sortCondition));
            selenium.WaitForPageToLoad("10000");
        }

        public void SearchSpecifiedComponent(string searchStr)
        {
            selenium.Type("searchText", searchStr);
            ClickAndWait("//fieldset[@class='search-actions']/button");
        }

        public void DownLoadModuleFromGallery(string moduleId,string version)  //moduleId eg:Orchard.Module.Orchard.CodeGeneration
        {          
           
            string downLoadLocator=string.Format("//a[contains(@href,'/Package/Download/{0}')]",moduleId);
            if (selenium.IsElementPresent(downLoadLocator))
                selenium.Click(downLoadLocator);
            try
            {
                //selenium.WaitForPopUp("_blank", "30000");
                //selenium.SelectWindow(selenium.GetAllWindowTitles()[1]);
                //selenium.SetSpeed("2000");               
                //selenium.KeyPressNative("13");
                LiveWriterHelper.InitRPF();
                string queryPopWinId = string.Format(@";Name = 'Opening {0}-{1}.nupkg' && Role = 'window'", moduleId, version);
                ScreenElement element;
                if (RPF.IsAvailable(6000, queryPopWinId))
                {
                    element = ScreenElement.FromPartialQueryId(string.Format(@";Name => 'Opening {0}-{1}.nupkg';[VisibleOnly]Role = 'grouping' ;[VisibleOnly]Name = 'Save File' && Role = 'radio button'", moduleId, version));
                    element.LeftButtonClick(1, 1);
                    element = ScreenElement.FromPartialQueryId(string.Format(@";Name => 'Opening {0}-{1}.nupkg';[VisibleOnly]Role = 'dialog';[VisibleOnly]Name = 'OK' && Role = 'push button'", moduleId, version));
                    element.LeftButtonClick(10, 10);
                    selenium.WaitForPageToLoad("3000");
                }
            }
            catch (Exception)
            { }
            finally
            {
                LiveWriterHelper.FinishRPF();
            }
            
        }
        public bool IsDownloadOk(string moduleId,string version)
        {

            bool result = true;
            string myDocumentsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            string dir = myDocumentsPath.Replace("Documents", "");
            dir = dir + "Downloads";
            if (Directory.Exists(dir))
            {
                if (File.Exists(dir + "\\" + moduleId +"-"+version+ ".nupkg"))
                    result = true;
                else result = false;
            }
            return result;
        }

        /// <summary>
        /// get the status of "installed sign" displayed or not
        /// </summary>
        /// <param name="intModuleIndexOfPageInGallery">ModuleIndex or ThemeIndex in Gallery</param>
        /// <returns></returns>
        public bool IsShowTheInstalledLabel(int intModuleIndexOfPageInGallery)
        {
            string moduleStyleLocatorInPage = string.Format("{0}[{1}]/div/div/div@class", UIHelperBase.ModulesListLocatorInGallery, intModuleIndexOfPageInGallery);
            if (selenium.GetAttribute(moduleStyleLocatorInPage).Contains("installed"))
                return true;
            else return false;
        }

        public bool IsFilterByKeyWordOK(string searchkeyWords)
        {
            int countSearch = (int)selenium.GetXpathCount("//div[@id='content']/div/form/ul/li");
            for (int i = 1; i <= countSearch; i++)
            {
                if (!selenium.GetText("//div[@id='content']/div/form/ul/li["+i+"]").Contains(searchkeyWords))
                    return false;
            }
            return true;

        }

        /// <summary>
        /// Check if the filter(By "Sort by" condition) result is correct.
        /// </summary>
        /// <param name="sortByString">indicate the sort condition("Downloads,Alphanumeric or Ratings </param>
        /// <param name="pageNo_Download">if need compare with next page or other page</param>
        /// <param name="pageNo_Alpha">page no need be compared with</param>
        /// <param name="pageNo_Ratings">page no need be compared with</param>
        /// <returns></returns>
        public bool IsFilterByApplySortOK(string sortByString,string pageNo_Download,string pageNo_Alpha,string pageNo_Ratings)
        {
            bool result=true;            
            switch (sortByString)
            {
                case "Downloads":
                    int downloads1 = Int32.Parse(selenium.GetText("//div[@id='content']/div/form/ul/li[1]/div[2]/div/div[@class='properties']/ul/li[3]").Substring(13));
                    if (!string.IsNullOrEmpty(pageNo_Download))
                    {
                        selenium.Click("link=" + pageNo_Download);
                        selenium.WaitForPageToLoad("9000");
                    }
                    int downloads2 = Int32.Parse(selenium.GetText("//div[@id='content']/div/form/ul/li[2]/div[2]/div/div[@class='properties']/ul/li[3]").Substring(13));
                    if ((downloads1 - downloads2) < 0) result = false; break;

                case "Alphanumeric" :
                    string moduleName1 = selenium.GetText("//div[@id='content']/div/form/ul/li[1]/div[2]/div[1]/div[1]/a/h2");
                    if (!string.IsNullOrEmpty(pageNo_Alpha))
                    {
                        selenium.Click("link=" + pageNo_Alpha);
                        selenium.WaitForPageToLoad("9000");
                    }
                    string moduleName2 = selenium.GetText("//div[@id='content']/div/form/ul/li[2]/div[2]/div[1]/div[1]/a/h2");
                    if(moduleName1.CompareTo(moduleName2) > 0) result=false; break;

                case "Ratings":
                    string rating1 = selenium.GetAttribute("//div[@id='content']/div/form/ul/li[1]/div[2]/div[1]/div[3]/ul/li[5]/div@title");
                    if (!string.IsNullOrEmpty(pageNo_Ratings))
                    {
                        selenium.Click("link=" + pageNo_Ratings);
                        selenium.WaitForPageToLoad("9000");
                    }
                    string rating2 = selenium.GetAttribute("//div[@id='content']/div/form/ul/li[10]/div[2]/div[1]/div[3]/ul/li[5]/div@title");
                    if(int.Parse(rating1.Substring(7, 2).Trim()) < int.Parse(rating2.Substring(7, 2).Trim())) result=false;break;
            }
            return result;
        }

        public bool IsFilterByApplySortOK_Module(string sortByString)
        {
            return IsFilterByApplySortOK(sortByString, "", "", "4");
        }
        public bool IsFilterByApplySortOK_Theme(string sortByString)
        {
            return IsFilterByApplySortOK(sortByString, "", "", "");
        }

        public void DeleteDownloadModuleFromLocal(string moduleId, string version)
        {
            string myDocumentsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            string dir = myDocumentsPath.Replace("Documents", "");
            dir = dir + "Downloads";
            if (Directory.Exists(dir))
            {
                if (File.Exists(dir + "\\" + moduleId + "-" + version + ".nupkg"))
                    try { File.Delete(dir + "\\" + moduleId + "-" + version + ".nupkg"); }
                    catch (Exception)
                    { }
            }
        }

        public void DownLoadThemeFromGallery(string themeId,string version)  
        {
            DownLoadModuleFromGallery(themeId, version);
        }
        public bool IsDownloadThemeOk(string themeId,string version)
        {
            return IsDownloadOk(themeId, version);
        }
        public void DeleteDownloadThemeFromLocal(string themeId, string version)
        {
            DeleteDownloadModuleFromLocal(themeId, version);
        }

        /// <summary>
        /// Filter Modules or Themes in Gallery
        /// </summary>
        /// <param name="feedFrom">eg:All feeds,Default</param>
        /// <param name="sortBy">eg:Downloads,Ratings or Alphanumeric</param>
        /// <param name="searchkeyWords">keyword of Theme or Module</param>
        public void FilterGallery(string feedFrom, string sortBy, string searchkeyWords)
        {
            if (!string.IsNullOrEmpty(feedFrom))
            {
                selenium.Click("apply-bulk-actions");
                selenium.Select("sourceId", "label=" + feedFrom);
            }
            selenium.WaitForPageToLoad("3000");
            if (!string.IsNullOrEmpty(sortBy))           
                ApplySortCondition(sortBy);
            selenium.WaitForPageToLoad("3000");
            if (!string.IsNullOrEmpty(searchkeyWords))
            {
                selenium.Type("searchText", searchkeyWords);
                selenium.Click("//div[@id='content']/div/form/fieldset[3]/button");
            }
            selenium.WaitForPageToLoad("3000");
        }

        public string GetPackagingVersion(PackagingType type,string packageIDInGallery)
        {
            if (type == PackagingType.Module)
            {
                if (!selenium.GetLocation().EndsWith("/Packaging/Gallery/Modules"))
                    selenium.Open("/Packaging/Gallery/Modules");
            }
            else if (type == PackagingType.Theme)
            {
                if (!selenium.GetLocation().EndsWith("/Packaging/Gallery/Themes"))
                    selenium.Open("/Packaging/Gallery/Themes");
            }
            string packagingDownLoadUrl =selenium.GetAttribute(string.Format("//a[contains(@href,'/Package/Download/{0}')]@href", packageIDInGallery));
            return packagingDownLoadUrl.Substring(packagingDownLoadUrl.LastIndexOf('/')+1);
        
        }

        
       


    }

    public enum PackagingType
    {
       Module,
       Theme
    }
    
    public class Feed
    {
        public string Title { get; set; }
        public string Url { get; set; }
        public Feed(string title, string url)
        {
            Title = title;
            Url = url;
        }
    }
}
